/**************************************************************
*  Apple LLVM version 10.0.0 (clang-1000.10.43.1)             *
*  Copyright (C) 2021 Xuan-Yu-San 307100890@qq.com.           *
*                                                             *
*  This file is part of little-nginx.                         *
*  Little-NGINX is a castration version NGINX for learning    *
*  HTTP Message.                                              *
*                                                             *
*  @file     Server.h                                         *
*  @github   https://gitee.com/xuanyusan/little_nginx.git     *
*  @license  MIT License (MIT)                                *
**************************************************************/

#ifndef SERVER_HPP
#define SERVER_HPP
#include "util.hpp"
#include "Logger.hpp"
#include "Socket.hpp"
#define Queue 20

/**
 * @author Xuan-Yu-San
 * @version 1.0.0
 * @date 20210914
 * @extends Socket
 * @brief HTTP Server
 * ...
*/
class Server:Socket {
public:
    Server(int, string);
    Connect create_connect();
    ~Server();
};

/**
 * Constructor for HTTP Server
 * @param socket_port listen port
 * @param socket_host server host
 * @return HTTP Server
*/
Server::Server(int socket_port, string socket_host="0.0.0.0"):Socket(socket_port, socket_host) {
    this->sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    #if defined(__APPLE__) && __cplusplus >= 199711L
    if(::bind(this->socket_id, (struct sockaddr*)&this->sockaddr, sizeof(this->sockaddr))==-1) {
    #else
    if(bind(this->socket_id, (struct sockaddr*)&this->sockaddr, sizeof(this->sockaddr))==-1) {
    #endif
        Logger_error("Bind error");
        exit(1);
    }
    if(listen(this->socket_id, Queue)==-1) {
        Logger_error("Listen error");
        exit(1);
    }
    Logger_info("listen", socket_port);
    queue<string> a = IP_config();
    while(!a.empty()) {
        Logger_info("Running on", concat_host_port("http://"+a.front(),socket_port));
        a.pop();
    }
}

Connect Server::create_connect() {
    socklen_t len = sizeof(this->sockaddr);
    int connect = accept(this->socket_id, (struct sockaddr*)&this->sockaddr, &len);
    if(connect<0) {
        Logger_error("Accept error");
        exit(1);
    }
    return Connect(connect, inet_ntoa(this->sockaddr.sin_addr));
}

Server::~Server() {}
#endif